package com.zhuiyun.project.api.onlineservice.component;


import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zhuiyun.project.api.onlineservice.entity.OnlineserviceChat;
import com.zhuiyun.project.api.onlineservice.service.impl.OnlineserviceChatServiceImpl;
import com.zhuiyun.project.utils.UploadFileUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @Description TODO 在线客服
 * @Author zhao
 * @Date 2024/2/27 15:26
 */
@ServerEndpoint(value = "/ws/{username}")   //权限放行，没有弄  在config里的WebSecurityConfig加一下
@Component
@Slf4j
public class WebSocketServers {

    public static final Map<String, Session> sessionMap=new ConcurrentHashMap<>();  //用于存储用户ID和对应的WebSocket会话Session之间的映射关系。

    private static final ConcurrentHashMap<Object,WebSocketServers> webSocketMap = new ConcurrentHashMap<>();  //用于存储WebSocketServers实例。

    private Session session;

    private static OnlineserviceChatServiceImpl onlineserviceChatService;

    @Autowired
    private void setOnlineserviceChatService( OnlineserviceChatServiceImpl onlineserviceChatService){  //初始化service方法，
        WebSocketServers.onlineserviceChatService=onlineserviceChatService;
    }

    public Session getSession() {
        return this.session;
    }

    private String username;
    private String kefu;


    /**
     *定时删除聊天记录，在线客服
     * @Description TODO
     * @Author zhao
     * @Date 2024/3/14 14:49
     */
    @Scheduled(fixedRate = 24 * 60 * 60 * 1000) //  24 * 60 * 60 *1000  一天
    public void dailyTask() {
        List<OnlineserviceChat> list= this.onlineserviceChatService.selectList();
        System.out.println(list+"================================");
        if(list.isEmpty()){
            System.out.println("暂时没有过期信息");
            return;
        }
        for (OnlineserviceChat onlineserviceChat : list) {
            if(this.onlineserviceChatService.del(onlineserviceChat.getId())>0){
                System.out.println("删除聊天记录成功");
            }else{
                System.out.println("删除聊天记录失败");
            }
        }
    }


    /**
     *  @OnOpen注解标记的方法，在WebSocket连接建立时触发。将用户ID和对应的WebSocket会话Session存储到sessionMap中。
     * @param session 是webSocket的会话对象，不是浏览器那个session
     * @param username  用户名
     *
     **/
    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
//        this.username = username;
        session.getUserProperties().put("username", username);
        sessionMap.put(username, session);
        log.info("建立连接===有新用户加入，username={},当前人数为，{}",username,sessionMap.size());

    }

    /**
     *  @Date 2024-2-27-15.28  在WebSocket连接关闭时触发
     * @param session 会话对象
     **/
    @OnClose
    public void onClose(Session session) throws IOException {
        String username = (String) session.getUserProperties().get("username");
        if(username.equals(this.username)){// 在用户关闭连接后，将客服的忙碌状态设置回false
            for (Session userSession : sessionMap.values()) {
                String sessionSenderId = (String) userSession.getUserProperties().get("username");
                if (sessionSenderId != null && sessionSenderId.equals(this.kefu)) {
                    userSession.getUserProperties().put("isBusy", false); // 将忙碌状态设置回false
                    System.out.println(this.username+"========================="+this.kefu);
                    break;
                }
            }
        }
        session.getUserProperties().remove("username");
        sessionMap.remove(username);
        log.info("关闭连接用户username={}的session", username);System.out.println("关闭连接");
    }

    /**
     *判断客服是否在线，是否忙碌
     * @param
     * @param username
     * @return
     */
    private String noKeFu(String receiverName,String username){
        boolean isUserOnline = false;
        boolean isUserBusy = false;
        for (Session userSession : sessionMap.values()) {
            String sessionSenderId = (String) userSession.getUserProperties().get("username");
            if (sessionSenderId != null && sessionSenderId.equals(username)) {
                isUserOnline = true;
                if (userSession.getUserProperties().containsKey("isBusy") && (boolean) userSession.getUserProperties().get("isBusy")) {  // 检查客服是否已经在会话中
                    isUserBusy = true;
                }
                userSession.getUserProperties().put("isBusy", true);// 在这里将客服的忙碌状态设置为true
                break;
            }
        }
        if (isUserOnline) {
            if (isUserBusy) {
                return  "chat"; // 客服忙碌，可以执行相应的操作
            } else {
                this.username =receiverName;  //成功与客服连接的，获取到名称，
                this.kefu=username;  //将客服的忙碌状态设置为false
                return "online";// 客服不忙碌，可以执行相应的操作
            }
        } else {
            return  "offline";// 客服不在线，可以执行相应的操作
        }
    }

    /**
     * 处理图片，视频，文件
     * @param type
     * @param formMessage
     * @param fileName
     * @return
     */
    private String noFile(String type,String formMessage,String fileName){
        if ("image".equals(type)) {// 处理图片类型
            System.out.println(formMessage);
            byte[] imageBytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(formMessage);
            MultipartFile imageFile = new MockMultipartFile("image.png", "image.png", MediaType.IMAGE_JPEG_VALUE, imageBytes);
            if (imageFile != null) {
                String imageUrl = UploadFileUtils.uploadFile(imageFile);
                String url= "http://101.43.223.224:8765/image/getImageById?id=" + imageUrl;
                log.info("图片链接: {}", url);
                return url;
            }
        } else if ("video".equals(type)) {  // 处理视频类型
            System.out.println(formMessage);
            byte[] videoBytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(formMessage);
            MultipartFile videoFile = new MockMultipartFile("video.mp4", "video.mp4", MediaType.APPLICATION_OCTET_STREAM_VALUE, videoBytes);
            if (videoFile != null) {
                String videoUrl = UploadFileUtils.uploadFile(videoFile);
                String url= "http://101.43.223.224:8765/image/getVideoById?id=" + videoUrl;
                log.info("视频链接: {}", url);
                return url;
            }
        } else if ("file".equals(type)) {// 处理文件类型
            System.out.println(formMessage);
            byte[] fileBytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(formMessage);
            MultipartFile file = new MockMultipartFile("file."+fileName, "file."+fileName, MediaType.TEXT_PLAIN_VALUE, fileBytes);
            if (file != null) {
                String fileUrl = UploadFileUtils.uploadFile(file);
                String url="http://101.43.223.224:8765/image/getFileById?id=" + fileUrl;
                log.info("文件链接: {}", url);
                return url;
            }
        }
        return null;
    }


    /**
     * @OnMessage注解标记的方法，在接收到客户端发送的消息时触发。解析消息内容，提取发送者ID、接收者ID、消息内容和时间等信息，然后根据接收者ID查找对应的Session，将消息发送给接收者。
     * @Date 2024-2-27-15.28  当客户端发送消息时调用
     * @param message 客户端发送的消息
     *
     **/
    @OnMessage
    public void onMessage(String message) throws IOException {
        try {
            if (message == null) {// 检查可能导致空指针异常的变量是否为null
                System.out.println("message空指针异常的变量");
                return;
            }
            JSONObject obj= JSONUtil.parseObj(message);


            OnlineserviceChat onChat=new OnlineserviceChat();
            onChat.setReceiverId(obj.getInt("receiverId")); //表示发送给哪个用户，比如admin
            onChat.setReceiverName(obj.getStr("receiverName"));//表示发送给哪个用户，比如admin
            onChat.setSenderId(obj.getInt("senderId")); //发送人id
            onChat.setUsername(obj.getStr("username")); //发送人姓名
            onChat.setMessage(obj.getStr("message"));  //发送信息
            onChat.setTime(obj.getDate("time"));  //发送时间
            onChat.setType(obj.getStr("type")); //发送类型
            onChat.setSetAvatarUrl(obj.getStr("setAvatarUrl"));//发信息人的头像
            String fileName=obj.getStr("file");

            if("kefu".equals(onChat.getType())){// 判断特定用户名的客服是否在线
                onChat.setMessage(noKeFu(onChat.getReceiverName(),onChat.getUsername()));
                System.out.println(onChat.getMessage());
            }

            if("image".equals(onChat.getType()) || "video".equals(onChat.getType())||"file".equals(onChat.getType())){ // 解码 base64 编码的数据
                onChat.setMessage(noFile(onChat.getType(),onChat.getMessage(),fileName));
                System.out.println(onChat.getMessage());
            }

            Session toSession=sessionMap.get(onChat.getReceiverName()); //根据to用户名来获取 session，再通过session发送信息文本
            JSONObject jsonObject=new JSONObject();//服务端 把信息组装一下，组装后的信息包含发送人和发送文本内容
            jsonObject.set("senderId",onChat.getSenderId());  //   发信息的人id
            jsonObject.set("username",onChat.getUsername());  //   发信息的人姓名
            jsonObject.set("message",onChat.getMessage()); // 同上  text一样
            jsonObject.set("receiverName",onChat.getReceiverName());  //   s收信息的人姓名
            jsonObject.set("receiverId",onChat.getReceiverId()); // s收信息的人id
            jsonObject.set("time",onChat.getTime()); // 同上 时间
            jsonObject.set("type",onChat.getType());  //发送类型
            jsonObject.set("setAvatarUrl",onChat.getSetAvatarUrl()); //发信息人的头像

            if(toSession!=null){
                toSession.getBasicRemote().sendText(jsonObject.toString());  //发消息给接收者
                log.info("发送给用户username:{}，信息,{}",onChat.getReceiverName(),jsonObject.toString());
                if(this.onlineserviceChatService.addOnLine(onChat)==0){
                    System.out.println("记录存储失败");
                }

                if("image".equals(onChat.getType()) || "video".equals(onChat.getType())||"file".equals(onChat.getType())){   //如果是图片，将发送给发送人，和发信息的人
                    Session toSession2 =sessionMap.get(onChat.getUsername()); //根据to用户名来获取 session，再通过session发送信息文本
                    if(toSession2!=null){
                        toSession2.getBasicRemote().sendText(jsonObject.toString());  //发消息给接收者,
                        log.info("发送给用户username:{}，信息,{}",onChat.getUsername(),jsonObject.toString());
                    }
                }
            }else{
                Session toSession2=sessionMap.get(onChat.getUsername());
                jsonObject.set("message", "对方当前不在线,请等待");  // 消息内容
                toSession2.getBasicRemote().sendText(jsonObject.toString());  // 发送消息给发送者

                log.info("发送失败，未找到用户username={}的session",onChat.getUsername());
            }
        } catch (NullPointerException e) { // 处理空指针异常，比如打印错误日志或者抛出自定义异常
            e.printStackTrace();
        }
    }



    /**
     * 用于向客户端发送消息的方法。将传入的消息内容通过WebSocket会话的getBasicRemote().sendText()方法发送给客户端。
     *  @Date 2024-2-27-15.28  服务推送消息
     * @param content
     * @throws IOException
     */
    public void sendMessage(String content) throws IOException {
        this.session.getBasicRemote().sendText(content);
    }





}